﻿#define _DEBUG_

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Inovance.InoMotionCotrollerShop.InoServiceContract.EtherCATConfigApi;
using System.Threading;

namespace example
{
    public partial class Form1 : Form
    {
        public List<int> mCaptPosList;
        public static UInt64 cardHandle;//轴卡操作句柄
        UInt32 retRtn; //函数接口返回值
        Int16 axNo = 0;//起始轴号
        Int16 count = 3;//轴数
        Int16 stopType = 1;//停止类型 0： 平滑停止 1： 急速停止
        Int16[] MaskAxNoArray = { 0, 1, 2 }; //指定立即直线立即插补的轴号
        Int16 axNum = 3; //参与的轴数量， [1,16]

        public Form1()
        {
            InitializeComponent();
        }

        #region 初始化
        //打印日志
        private void ShowMessage(string msg)
        {            
            listBox_RunSts.Items.Add(DateTime.Now.ToString() + " " + msg);
            listBox_RunSts.SelectedIndex = listBox_RunSts.Items.Count - 1;
            listBox_RunSts.SelectedIndex = -1;
        }
        //卡初始化
        private void button_CardInit_Click(object sender, EventArgs e)
        {
            UInt32 masterStatus = 0;
            int cardNo = 0; //打开0号卡
            Int32 cardsNum = 0;
            try
            {
                //非必须步骤，读取电脑中轴卡的数量
                retRtn = ImcApi.IMC_GetCardsNum(ref cardsNum);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage("IMC_GetCardsNum failed 故障代码为：0x" + retRtn.ToString("x8"));
                }
                textBox_CardNum.Text = cardsNum.ToString();
                //【1】获取轴卡操作句柄
                retRtn = ImcApi.IMC_OpenCardHandle(cardNo, ref cardHandle);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage("IMC_OpenCardHandle failed 故障代码为：0x" + retRtn.ToString("x8"));
                }
                //【2】获取主站状态
                retRtn = ImcApi.IMC_GetECATMasterSts(cardHandle, ref masterStatus);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage("IMC_GetECATMasterSts failed 故障代码为：0x" + retRtn.ToString("x8"));
                }
                else
                {
                    if (masterStatus != ImcApi.EC_MASTER_OP)
                    {
                        //【3】下载设备参数
                        //deviceconfig.xml文件是由控制卡后台软件配置生成然后手动放到编译路径下，路径可自由选择；
                        retRtn = ImcApi.IMC_DownLoadDeviceConfig(cardHandle, ".\\deviceconfig.xml");
                        if (retRtn != ImcApi.EXE_SUCCESS)
                        {
                            ShowMessage("IMC_DownLoadDeviceConfig failed 故障代码为：0x" + retRtn.ToString("x8"));
                        }
                        //【4】启动总线
                        retRtn = ImcApi.IMC_ScanCardECAT(cardHandle, 1);            //0表示非阻塞式开卡，1表示阻塞式开卡；
                        if (retRtn != ImcApi.EXE_SUCCESS)
                        {
                            ShowMessage("IMC_ScanCardECAT failed 故障代码为：0x" + retRtn.ToString("x8"));
                        }
                        //【5】下载系统参数
                        //systemconfig.xml文件是由控制卡后台软件配置生成然后手动放到编译路径下，路径可自由选择；
                        retRtn = ImcApi.IMC_DownLoadSystemConfig(cardHandle, ".\\systemconfig.xml");
                        if (retRtn != ImcApi.EXE_SUCCESS)
                        {
                            ShowMessage("IMC_DownLoadSystemConfig failed 故障代码为：0x" + retRtn.ToString("x8"));
                        }
                    }
                }

                timer_UI.Enabled = true;
                textBox_CardNum.Text = cardsNum.ToString();
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }
        }
        //关闭卡
        private void button_CloseCard_Click(object sender, EventArgs e)
        {
            try
            {
                timer_UI.Enabled = false;
                retRtn = ImcApi.IMC_CloseCard(cardHandle);
                //retRtn = ImcApi.IMC_CloseCardHandle(cardHandle);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }
        }
        #endregion

        #region 控制
        //使能
        private void button_AxServoOn_Click(object sender, EventArgs e)
        {
            try
            {
                retRtn = ImcApi.IMC_AxServoOn(cardHandle, axNo, count);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }
        }
        //下使能
        private void button_AxServoOff_Click(object sender, EventArgs e)
        {
            try
            {
                retRtn = ImcApi.IMC_AxServoOff(cardHandle, axNo, count);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }
        }
        //停止
        private void button_AxMoveStop_Click(object sender, EventArgs e)
        {
            try
            {
                stopType = 1;//停止类型 0： 平滑停止 1： 急速停止
                retRtn = ImcApi.IMC_AxMoveStop(cardHandle, axNo, stopType);// 0平滑停止；1 急停停止
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }
        }
        //清除轴状态
        private void button_ClrAxSts_Click(object sender, EventArgs e)
        {
            try
            {
                for (Int16 i = axNo; i < count; i++)
                {
                    retRtn = ImcApi.IMC_ClrAxSts(cardHandle, i);
                }
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }
        }
        #endregion

        #region 轴状态与信息显示
        //将十进制整形转换为二进制显示的字符串
        private string ConvertDecimalToBinary(Int32 nAxSts) 
        {
            string strAxSts = "";
            Int32 nBitValue = 0x00;

            for (uint i = 0; i < 11; i++)
            {
                nBitValue = (Int32)(0x01 * Math.Pow(2.0, i));    //对nBitValue向左移1位，移到第几位通过i来控制
                if ((nAxSts & nBitValue) == nBitValue)
                {
                    strAxSts = "1" + strAxSts;
                }
                else
                {
                    strAxSts = "0" + strAxSts;
                }
            }
            return strAxSts;
        }
        //UI界面信息刷新
        private void timer_UI_Tick(object sender, EventArgs e)
        {
            try
            {
                timer_UI.Enabled = false;
                double[] PrfPosArray = { 0,1,2 };
                double[] EncPosArray = { 0, 1, 2 };
                double[] EncVelArray = { 0, 1, 2 };
                Int32[] AxStsArray = { 0, 1, 2 };
                double TrajVel = 0;//读取合成速度
                //获取目标位置
                retRtn = ImcApi.IMC_GetAxPrfPos(cardHandle, axNo, PrfPosArray, count);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage("IMC_GetAxSts failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }
                //获取反馈位置
                retRtn = ImcApi.IMC_GetAxEncPos(cardHandle, axNo, EncPosArray, count);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage("IMC_GetAxEncPos failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }
                //获取反馈速度
                retRtn = ImcApi.IMC_GetAxEncVel(cardHandle, axNo, EncVelArray, count);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage("IMC_GetAxSts failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }
                //获取伺服状态
                retRtn = ImcApi.IMC_GetAxSts(cardHandle, axNo, AxStsArray, count);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage("IMC_GetAxSts failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }

                textBox_AxPrfPos0.Text = PrfPosArray[0].ToString();
                textBox_AxPrfPos1.Text = PrfPosArray[1].ToString();
                textBox_AxPrfPos2.Text = PrfPosArray[2].ToString();
                textBox_AxEncPos0.Text = EncPosArray[0].ToString();
                textBox_AxEncPos1.Text = EncPosArray[1].ToString();
                textBox_AxEncPos2.Text = EncPosArray[2].ToString();
                textBox_AxEncVel0.Text = EncVelArray[0].ToString();
                textBox_AxEncVel1.Text = EncVelArray[1].ToString();
                textBox_AxEncVel2.Text = EncVelArray[2].ToString();
                //转化为二进制字符串显示
                textBox_AxSts0.Text = ConvertDecimalToBinary(AxStsArray[0]);
                textBox_AxSts1.Text = ConvertDecimalToBinary(AxStsArray[1]);
                textBox_AxSts2.Text = ConvertDecimalToBinary(AxStsArray[2]);         
                //到位信号判断
                textBox_AxStsArrive0.Text = (AxStsArray[0] & 0xC) == 0x8 ? "1" : "0";
                textBox_AxStsArrive1.Text = (AxStsArray[1] & 0xC) == 0x8 ? "1" : "0";
                textBox_AxStsArrive2.Text = (AxStsArray[2] & 0xC) == 0x8 ? "1" : "0";                
                //获取多轴插补立即运动合成速度 功 能：读取多轴同步运动系统信息
                if ((AxStsArray[0] & ImcApi.AX_BUSY_BIT) == ImcApi.AX_BUSY_BIT)
                {
                    retRtn = ImcApi.IMC_ImmediateMoveGetVel(cardHandle, axNo, ref TrajVel);
                    if (retRtn != ImcApi.EXE_SUCCESS)
                    {
                        ShowMessage("IMC_ImmediateMoveGetVel failed 故障代码为：0x" + retRtn.ToString("x8"));
                        return;
                    }
                }
                textBox_ImmediateMoveGetVel.Text = TrajVel.ToString();

                timer_UI.Enabled = true;
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }            
        }
        #endregion

        #region 功能测试
        //功 能： 多轴直线立即插补（ 按所有轴的合成速度、加速度减速度进行规划）
        private void button_ImmediateLineMoveInSynVelAcc_Click(object sender, EventArgs e)
        {
            try
            {
                double[] EndPosArray = { 10000, 10000, 10000 }; //直线的终点位置，根据 axNum 值， 应传入 axNum 维终点位置数组， 参数范围[-2147483647,2147483647]
                double trajVel = 100000; //插补合成速度，参数范围[1e-6,1e9]
                double trajAcc = 100000; //插补合成加速度，参数范围[1e-6,1e9]
                double trajDec = 100000; //插补合成减速度，参数范围[1e-6,1e9]
                double smoothCoef = 50; //平滑系数： [0,200]
                Int16 type = 1;//位置类型： 0 绝对， 1 相对
                retRtn = ImcApi.IMC_ImmediateLineMoveInSynVelAcc(cardHandle, MaskAxNoArray, axNum, EndPosArray, trajVel, trajAcc, trajDec, smoothCoef, type);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
                }
                else
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " 成功");
                }
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }
        }
        //功 能： 多轴直线立即插补（ 按各个轴的速度、加速度减速度进行规划， 取最短板运动参数）
        private void button_ImmediateLineMoveInAxisVelAcc_Click(object sender, EventArgs e)
        {
            try
            {
                double[] EndPosArray = { 0, 0, 0 }; //直线的终点位置，根据 axNum 值， 应传入 axNum 维终点位置数组， 参数范围[-2147483647,2147483647]
                double AxVelArray = 100000; //参与轴的各轴速度，根据 axNum 值， 应传入 axNum 维速度数组，参数范围[1e-6,1e9]
                double AxAccArray = 100000; //参与轴的各轴加速度，根据 axNum 值， 应传入 axNum 维加速度数组，参数范围[1e-6,1e9]
                double AxDecArray = 100000; //参与轴的各轴减速度，根据 axNum 值， 应传入 axNum 维减速度数组，参数范围[1e-6,1e9]
                double smoothCoef = 50; //平滑系数： [0,200]
                Int16 type = 0;//位置类型： 0 绝对， 1 相对
                //IMC_ImmediateLineMoveInAxisVelAcc(HANDLETYPE cardHandle, Int16[] pMaskAxNo, Int16 axNum, double[] pEndPos, ref double pAxVel, ref double pAxAcc, ref double pAxDec, double smoothCoef, Int16 type);
                retRtn = ImcApi.IMC_ImmediateLineMoveInAxisVelAcc(cardHandle, MaskAxNoArray, axNum, EndPosArray, ref AxVelArray, ref AxAccArray, ref AxDecArray, smoothCoef, type);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
                }
                else
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " 成功");
                }
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }
        }
        //功 能： 三点描述圆弧立即插补运动（关键参数与软件编程手册4.10 插补模式中的一致）
        private void button_ImmediateArcThreePointMove_Click(object sender, EventArgs e)
        {
            //double[] MidPosArray = { 5000, 5000, 0 }; //圆弧的第二点坐标， 当 axNum 为 2 时，传入为 2 维数组； 为 3 时， 应传入 3 维数组位置， 参数范围[-2147483647,2147483647]
            double[] MidPosArray = { 5000, 0, 5000 }; //圆弧的第二点坐标， 当 axNum 为 2 时，传入为 2 维数组； 为 3 时， 应传入 3 维数组位置， 参数范围[-2147483647,2147483647]
            double[] EndPosArray = { 10000, 0, 0 }; //圆弧的终点坐标， 当 axNum 为 2 时，传入为 2 维数组； 为 3 时， 应传入 3 维数组位置， 参数范围[-2147483647,2147483647]
            double trajVel = 1000; //插补合成速度，参数范围[1e-6,1e9]
            double trajAcc = 1000000; //插补合成加速度，参数范围[1e-6,1e9]
            double trajDec = 2000000; //插补合成减速度，参数范围[1e-6,1e9]
            double smoothCoef = 50; //平滑系数： [0,200]
            Int16 type = 1;//位置类型： 0 绝对， 1 相对
            retRtn = ImcApi.IMC_ImmediateArcThreePointMove(cardHandle, MaskAxNoArray, axNum, MidPosArray, EndPosArray, trajVel, trajAcc, trajDec, smoothCoef, type);
            if (retRtn != ImcApi.EXE_SUCCESS)
            {
                ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
            }
            else
            {
                ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " 成功");
            }
        }
        //功 能： 圆心终点描述形式圆弧立即插补运动
        private void button_ImmediateArcCenterMove_Click(object sender, EventArgs e)
        {
            double[] CenterArray = { 5000, 0, 0 }; //圆 心 位 置 ， 2 维 数 组 ， 表 示 圆 弧 XY 平 面 的 圆 心 坐 标 ， 参 数 范 围 [-2147483647,2147483647]
            double[] EndPosArray = { 10000, 0, 0 }; //终 点 位 置 ， 2 维 数 组 ， 表 示 圆 弧 XY 平 面 的 终 点 坐 标 ， 参 数 范 围 [-2147483647,2147483647]
            Int16 dir = 1;//1 圆弧逆时针方向运动 -1 圆弧顺时针方向运动
            double height = 10000;//螺 旋 线 的 螺 距 ： 当 为 平 面 圆 弧 时 ， 该 值 应 该 设 置 为 0 ， 参 数 范 围 [-2147483647,2147483647]
            int turn = 1;//圆弧的整圈插补数， 参数范围[0,1e8]
            double trajVel = 10000; //插补合成速度，参数范围[1e-6,1e9]
            double trajAcc = 1000000; //插补合成加速度，参数范围[1e-6,1e9]
            double trajDec = 2000000; //插补合成减速度，参数范围[1e-6,1e9]
            double smoothCoef = 50; //平滑系数： [0,200]
            Int16 type = 1;//位置类型： 0 绝对， 1 相对
            retRtn = ImcApi.IMC_ImmediateArcCenterMove(cardHandle, MaskAxNoArray, axNum, CenterArray, EndPosArray, dir, height, turn, trajVel, trajAcc, trajDec, smoothCoef, type);
            if (retRtn != ImcApi.EXE_SUCCESS)
            {
                ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
            }
            else
            {
                ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " 成功");
            }
        }
        //功 能： 半径描述形式圆弧立即插补
        private void button_ImmediateArcRadiusMove_Click(object sender, EventArgs e)
        {
            double radius=5000;//圆弧半径
            double[] EndPosArray = { 10000, 0, 0 }; //终 点 位 置 ， 2 维 数 组 ， 表 示 圆 弧 XY 平 面 的 终 点 坐 标 ， 参 数 范 围 [-2147483647,2147483647]
            Int16 dir = 1;//1 圆弧逆时针方向运动 -1 圆弧顺时针方向运动
            double height = 10000;//螺 旋 线 的 螺 距 ： 当 为 平 面 圆 弧 时 ， 该 值 应 该 设 置 为 0 ， 参 数 范 围 [-2147483647,2147483647]
            int turn = 1;//圆弧的整圈插补数， 参数范围[0,1e8]
            double trajVel = 10000; //插补合成速度，参数范围[1e-6,1e9]
            double trajAcc = 1000000; //插补合成加速度，参数范围[1e-6,1e9]
            double trajDec = 2000000; //插补合成减速度，参数范围[1e-6,1e9]
            double smoothCoef = 50; //平滑系数： [0,200]
            Int16 type = 1;//位置类型： 0 绝对， 1 相对
            retRtn = ImcApi.IMC_ImmediateArcRadiusMove(cardHandle, MaskAxNoArray, axNum, radius, EndPosArray, dir, height, turn, trajVel, trajAcc, trajDec, smoothCoef, type);
            if (retRtn != ImcApi.EXE_SUCCESS)
            {
                ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
            }
            else
            {
                ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " 成功");
            }
        }
        //功 能： 圆心圆心角描述方式圆弧立即插补
        private void button_ImmediateArcAngleMove_Click(object sender, EventArgs e)
        {            
            double[] CenterArray = { 5000, 0, 0 }; //圆 心 位 置 ， 2 维 数 组 ， 表 示 圆 弧 XY 平 面 的 圆 心 坐 标 ， 参 数 范 围 [-2147483647,2147483647]
            double angle=-Math.PI;//圆弧的角度大小：单位弧度
            double height = 0;//螺 旋 线 的 螺 距 ： 当 为 平 面 圆 弧 时 ， 该 值 应 该 设 置 为 0 ， 参 数 范 围 [-2147483647,2147483647]
            double trajVel = 1000; //插补合成速度，参数范围[1e-6,1e9]
            double trajAcc = 1000000; //插补合成加速度，参数范围[1e-6,1e9]
            double trajDec = 2000000; //插补合成减速度，参数范围[1e-6,1e9]
            double smoothCoef = 50; //平滑系数： [0,200]
            retRtn = ImcApi.IMC_ImmediateArcAngleMove(cardHandle, MaskAxNoArray, axNum, CenterArray, angle, height, trajVel, trajAcc, trajDec, smoothCoef);
            if (retRtn != ImcApi.EXE_SUCCESS)
            {
                ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
            }
            else
            {
                ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " 成功");
            }
        }
        //功 能： 平滑停止该模式对应的立即指令运动：注意： axNo 表示参与插补其中的的任意一个轴号
        private void button_ImmediateMoveStop_Click(object sender, EventArgs e)
        {
            try
            {
                retRtn = ImcApi.IMC_ImmediateMoveStop(cardHandle, axNo);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }
        }
        //功 能： 按设定的急停减速度停止对应的指令运动，注意： axNo 表示参与插补其中的的任意一个轴号
        private void button_ImmediateMoveEStop_Click(object sender, EventArgs e)
        {
            double estopDec = 100000000;//停止急停减速度，为合成停止减速度，参数范围[1e-6,1e9]
            try
            {
                retRtn = ImcApi.IMC_ImmediateMoveEStop(cardHandle, axNo, estopDec);
                if (retRtn != ImcApi.EXE_SUCCESS)
                {
                    ShowMessage(System.Reflection.MethodBase.GetCurrentMethod().Name + " failed 故障代码为：0x" + retRtn.ToString("x8"));
                    return;
                }
            }
            catch (Exception ex)
            {
                ShowMessage(ex.ToString());
            }
        }
        #endregion
    }
}
